package com.tbit.main.util;

import com.tbit.main.pojo.OssConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import java.io.*;
import java.net.SocketException;
import java.util.UUID;

/**
 * @Author: chen
 * @Description: ftp文件传输
 * @Date: 创建于 19:48 2022/7/13
 */
@Slf4j
public class FtpUtils {


    /**
     * @param ftpIp       FTP IP
     * @param ftpUserName FTP 用户名
     * @param ftpPassword FTP密码
     * @param ftpPort     FTP 端口号
     * @param ftpPath     FTP文件所在路径
     * @param localPath   本地路径
     * @param fileName    文件名
     */
    public static void downloadFtpFile(String ftpIp, String ftpUserName, String ftpPassword, int ftpPort, String ftpPath, String localPath, String fileName) {
        FTPClient ftpClient = null;
        try {
            ftpClient = getFTPClient(ftpIp, ftpUserName, ftpPassword, ftpPort);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.changeWorkingDirectory(ftpPath);

            //判断本地路径是否存在，不存在进行创建
            File file1 = new File(localPath);
            if (!file1.exists()) {
                file1.mkdirs();
            }

            //把文件写入到本地路径
            File localFile = new File(localPath + fileName);
            OutputStream os = new FileOutputStream(localFile);
            ftpClient.setControlEncoding("UTF-8"); // 中文支持
            ftpClient.enterLocalPassiveMode();//这个方法的意思就是每次数据连接之前，ftp client告诉ftp server开通一个端口来传输数据。为什么要这样做呢，因为ftp server可能每次开启不同的端口来传输数据，但是在linux上，由于安全限制，可能某些端口没有开启，所以就出现阻塞。
            ftpClient.retrieveFile(fileName, os);
            os.close();
            ftpClient.logout();
        } catch (FileNotFoundException e) {
            System.out.println("没有找到文件");
            log.error("没有找到要下载的文件" + ftpPath);
        } catch (SocketException e) {
            System.out.println("连接失败");
            log.error("连接下载文件的FTP失败" + ftpPath);
        } catch (IOException e) {
            System.out.println("读写异常");
            log.error("读写文件异常" + ftpPath);
        }
    }


    /**
     * @param url         FTP服务器hostname
     * @param port        FTP服务器端口
     * @param username    FTP登录账号
     * @param password    FTP登录密码
     * @param path        FTP服务器保存目录
     * @param filename    文件名 6403_APP_YYYYMMDD_渠道标志_批次号.txt
     * @param inputStream 输入流
     * @return
     */
    private static boolean uploadFileFTP(String url, int port, String username, String password,
                                         String path, String filename, InputStream inputStream) {


        boolean success;
        FTPClient ftp = new FTPClient();
        try {
            ftp = getFTPClient(url, username, password, port);
            int reply;
            // 返回链接码
            reply = ftp.getReplyCode();
            // 设置文件格式为二进制类型
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                log.info("FTP服务器 拒绝连接");
                return false;
            }
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftp.makeDirectory(path);
            // 跳转到指定的目录路径
            ftp.changeWorkingDirectory(path);
            ftp.enterLocalPassiveMode();
            // 存储文件
            ftp.storeFile(filename, inputStream);
            inputStream.close();
            ftp.logout();
            success = true;
        } catch (IOException e) {
            log.error("FTP服务器 文件上传失败 失败原因：{}", e.getMessage(), e);
            return false;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException e) {
                    log.error("FTP服务器 关闭失败 失败原因：{}", e.getMessage(), e);
                }
            }
        }
        return success;
    }


    /**
     * 文件下载（流形式）
     *
     * @param ftpIp       FTP IP
     * @param ftpUserName FTP 用户名
     * @param ftpPassword FTP密码
     * @param ftpPort     FTP 端口号
     * @param ftpPath     FTP文件所在路径
     * @param fileName    文件名
     * @return
     */
    public static String loadFtpFile(String ftpIp, String ftpUserName, String ftpPassword,
                                     int ftpPort, String ftpPath, String fileName, OssConfig ossConfig) {
        FTPClient ftpClient = null;
        try {
            ftpClient = getFTPClient(ftpIp, ftpUserName, ftpPassword, ftpPort);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.changeWorkingDirectory(ftpPath);
            ftpClient.setControlEncoding("UTF-8"); // 中文支持
            ftpClient.enterLocalPassiveMode();//这个方法的意思就是每次数据连接之前，ftp client告诉ftp server开通一个端口来传输数据。为什么要这样做呢，因为ftp server可能每次开启不同的端口来传输数据，但是在linux上，由于安全限制，可能某些端口没有开启，所以就出现阻塞。
            InputStream inputStream = ftpClient.retrieveFileStream(fileName);
            String imageId = UUID.randomUUID().toString();
            String contentType = fileName.substring(fileName.lastIndexOf(".") + 1);
            String name = OssFileUtils.uploadByAliYun(inputStream, ossConfig, imageId, contentType, 2);
            ftpClient.logout();
            return name;
        } catch (FileNotFoundException e) {
            System.out.println("没有找到文件");
            log.error("没有找到要下载的文件" + ftpPath);
        } catch (SocketException e) {
            System.out.println("连接失败");
            log.error("连接下载文件的FTP失败" + ftpPath);
        } catch (IOException e) {
            System.out.println("读写异常");
            log.error("读写文件异常" + ftpPath);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 删除文件
     *
     * @param ftpIp       FTP IP
     * @param ftpUserName FTP 用户名
     * @param ftpPassword FTP密码
     * @param ftpPort     FTP 端口号
     * @param ftpPath     FTP文件所在路径
     * @param fileName    文件名
     * @return
     */
    public static boolean deleteFile(String ftpIp, String ftpUserName, String ftpPassword, int ftpPort, String ftpPath, String fileName) {
        FTPClient ftpClient = null;
        try {
            ftpClient = getFTPClient(ftpIp, ftpUserName, ftpPassword, ftpPort);
            ftpClient.setControlEncoding("UTP-8");
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalActiveMode();
            ftpClient.changeWorkingDirectory(ftpPath);
            boolean result = ftpClient.deleteFile(fileName);
            ftpClient.logout();
            return result;
        } catch (FileNotFoundException e) {
            System.out.println("没有找到文件");
            log.error("没有找到要下载的文件" + ftpPath);
        } catch (SocketException e) {
            System.out.println("连接失败");
            log.error("连接下载文件的FTP失败" + ftpPath);
        } catch (IOException e) {
            System.out.println("读写异常");
            log.error("读写文件异常" + ftpPath);
        }
        return false;
    }

    /**
     * @param ftpIp       FTP的IP
     * @param ftpUserName ftp用户名
     * @param ftpPassword ftp密码
     * @param ftpPort     ftp端口号
     * @return
     */
    public static FTPClient getFTPClient(String ftpIp, String ftpUserName, String ftpPassword, int ftpPort) {
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient = new FTPClient();
            ftpClient.setConnectTimeout(10000 * 10000);
            ftpClient.connect(ftpIp, ftpPort);
            ftpClient.login(ftpUserName, ftpPassword);
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                System.out.println("未连接到FTP");
            } else {
                System.out.println("连接成功Ftp");
            }
        } catch (SocketException e) {
            log.error(e.getMessage(), e);
            log.error("连接下载文件的FTP失败");
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return ftpClient;
    }


}
